package com.zrc.japktool.ui.view;

import javafx.application.Platform;
import javafx.scene.control.TextArea;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EnumSet;
import java.util.Set;

public class LogTextArea extends TextArea {
    // 日志级别枚举（颜色+前缀）
    public enum LogLevel {
        DEBUG(Color.GRAY, "[DEBUG]"),
        INFO(Color.BLACK, "[INFO]"),
        WARN(Color.ORANGE, "[WARN]"),
        ERROR(Color.RED, "[ERROR]");

        private final Color color;
        private final String prefix;

        LogLevel(Color color, String prefix) {
            this.color = color;
            this.prefix = prefix;
        }

        public Color getColor() {
            return color;
        }

        public String getPrefix() {
            return prefix;
        }
    }

    private Set<LogLevel> enabledLevels = EnumSet.allOf(LogLevel.class);
    private final SimpleDateFormat timeFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private int maxLogLines = 1000;

    public LogTextArea() {
        initStyle();
    }

    /**
     * 初始化基础样式
     */
    private void initStyle() {
        setEditable(false); // 禁止编辑
        setWrapText(true);  // 自动换行
        setPadding(new javafx.geometry.Insets(8)); // 内边距
        setStyle("-fx-font-family: 'Microsoft YaHei', 'SimSun'; -fx-font-size: 12px;");
    }

    /**
     * 核心：添加日志（主线程执行+直接设置文本颜色）
     */
    public void addLog(LogLevel level, String message) {
        if (!enabledLevels.contains(level)) return;

        Platform.runLater(() -> {
            // 1. 构建日志内容（带时间戳）
            String time = timeFormatter.format(new Date());
            String logPrefix = String.format("[%s] %s ", time, level.getPrefix());
            String fullLog = logPrefix + message + "\n";

            // 2. 记录当前文本长度（用于后续颜色设置）
            int startIdx = getText().length();
            appendText(fullLog);
            int endIdx = getText().length();

            // 3. 为日志前缀和内容设置颜色
            setRangeColor(startIdx, endIdx, level.getColor());

            // 4. 修剪日志（防止内存溢出）
            trimExcessLogs();
        });
    }

    /**
     * 关键修复：直接设置文本片段的颜色（绕过CSS，确保生效）
     */
    private void setRangeColor(int start, int end, Color color) {
        // 遍历TextArea的内容节点，寻找Text节点来设置颜色
        int currentPos = 0;
        for (Node node : getChildrenUnmodifiable()) {
            if (node instanceof TextFlow textFlow) {
                for (Node child : textFlow.getChildren()) {
                    if (child instanceof Text textNode) {
                        int nodeStart = currentPos;
                        int nodeEnd = currentPos + textNode.getText().length();

                        // 判断当前文本节点是否与目标范围有重叠
                        if (nodeEnd > start && nodeStart < end) {
                            int localStart = Math.max(0, start - nodeStart);
                            int localEnd = Math.min(textNode.getText().length(), end - nodeStart);

                            // 创建带颜色的文本片段并替换原内容
                            String text = textNode.getText();
                            Text coloredNode = new Text(text.substring(localStart, localEnd));
                            coloredNode.setFill(color);

                            // 替换原文本节点中的对应部分
                            Text newText = new Text(text.substring(0, localStart));
                            newText.setFill(textNode.getFill());
                            Text remainingText = new Text(text.substring(localEnd));
                            remainingText.setFill(textNode.getFill());

                            textFlow.getChildren().remove(textNode);
                            textFlow.getChildren().addAll(newText, coloredNode, remainingText);
                        }

                        currentPos = nodeEnd;
                    }
                }
            }
        }
    }

    /**
     * 修剪日志：超过最大行数时删除最早的日志
     */
    private void trimExcessLogs() {
        String[] logs = getText().split("\n");
        if (logs.length <= maxLogLines) return;

        // 保留最后maxLogLines行
        int start = logs.length - maxLogLines;
        StringBuilder newLogs = new StringBuilder();
        for (int i = start; i < logs.length; i++) {
            newLogs.append(logs[i]).append("\n");
        }

        // 重置文本（颜色会被清空，需重新初始化样式）
        setText(newLogs.toString());
        initStyle(); // 恢复基础样式
    }

    public void clearLogs() {
        setText("");
        initStyle(); // 重置样式
    }

    public void setEnabledLevels(Set<LogLevel> enabledLevels) {
        this.enabledLevels = enabledLevels != null ? enabledLevels : EnumSet.allOf(LogLevel.class);
    }

    public void setMaxLogLines(int maxLogLines) {
        this.maxLogLines = Math.max(maxLogLines, 100);
    }

    // 快捷添加日志
    public void debug(String msg) {
        addLog(LogLevel.DEBUG, msg);
    }

    public void info(String msg) {
        addLog(LogLevel.INFO, msg);
    }

    public void warn(String msg) {
        addLog(LogLevel.WARN, msg);
    }

    public void error(String msg) {
        addLog(LogLevel.ERROR, msg);
    }
}